﻿using GameView.Models;
using GameView.Services.Comment;
using HPSocket;
using HPSocket.Tcp;
using System.Text;

namespace GameView.Comment
{
    public class HPSocketTcpClientService : IDisposable
    {
        private ITcpPackClient _tcpClient;
        private bool _disposed = false;

        // 事件定义
        public event Action<string> OnStatusChanged;

        public event Action<byte[]> OnDataReceived;

        public event Action<string> OnError;

        public HPSocketTcpClientService()
        {
            _tcpClient = new TcpPackClient();
            _tcpClient.Address = "222.211.91.224";
            _tcpClient.Port = 2236;
            _reconnectCts = new CancellationTokenSource();

            // 事件绑定
            _tcpClient.OnConnect += OnConnect;
            _tcpClient.OnReceive += OnReceive;
            _tcpClient.OnClose += OnClose;

            // 设置数据包最大长度(根据实际需求调整)
            _tcpClient.MaxPackSize = 1024 * 1024; // 1MB
        }

        public bool Send(string msg)
        {
            var bytes = Encoding.UTF8.GetBytes(msg);
            return _tcpClient.Send(bytes, bytes.Length);
        }

        public bool Connect()
        {
            try
            {
                //OnStatusChanged?.Invoke($"正在链接到服务器...");
                return _tcpClient.Connect();
            }
            catch (Exception ex)
            {
                OnError?.Invoke($"链接失败: {ex.Message}");
                return false;
            }
        }

        public bool Connect(string address, ushort port)
        {
            try
            {
                return _tcpClient.Connect(address, port);
            }
            catch (Exception ex)
            {
                OnError?.Invoke($"链接失败: {ex.Message}");
                return false;
            }
        }

        public void Disconnect()
        {
            if (_tcpClient.State != ServiceState.Stopped)
            {
                _tcpClient.StopAsync().ConfigureAwait(false);
            }
        }

        #region HPSocket事件处理

        private HandleResult OnConnect(IClient sender)
        {
            //OnStatusChanged?.Invoke("已连接服务器！");
            var name = string.Empty;
            if (StaticValues.LoginInfo.PersonInfo.ParentId > 0)
                name = $"{StaticValues.LoginInfo.PersonInfo.IdCard}/";
            name += StaticValues.LoginInfo.PersonInfo.Account;
            var json = JSON.Serialize(new ConnectedInitMessage(name));
            var bytes = Encoding.UTF8.GetBytes(json);
            var res = sender.Send(bytes, bytes.Length);
            if (res)
                return HandleResult.Ok;
            return HandleResult.Error;
        }

        private HandleResult OnClose(IClient sender, SocketOperation socketOperation, int errorCode)
        {
            OnStatusChanged?.Invoke($"服务器链接断开. 操作类型: {socketOperation}, 错误码: {errorCode}");
            if (!_disposed)
                TryReconnect();
            return HandleResult.Ok;
        }

        private HandleResult OnReceive(IClient sender, byte[] data)
        {
            OnDataReceived?.Invoke(data);
            return HandleResult.Ok;
        }

        #endregion HPSocket事件处理

        #region （指数退避）

        private const int MaxReconnectAttempts = 5;          // 最大重试次数
        private const int InitialReconnectDelayMs = 10000;    // 初始重试延迟10秒
        private const int MaxReconnectDelayMs = 8 * 20000;       // 最大延迟30秒
        private const double BackoffMultiplier = 2.0;        // 退避乘数
        private int _reconnectAttempts = 0;
        private int _currentReconnectDelay = InitialReconnectDelayMs;
        private CancellationTokenSource _reconnectCts;
        private readonly object _reconnectLock = new object();

        private void TryReconnect()
        {
            lock (_reconnectLock)
            {
                if (_reconnectAttempts >= MaxReconnectAttempts)
                {
                    OnStatusChanged?.Invoke($"已达到最大重连次数({MaxReconnectAttempts})，停止重连");
                    return;
                }

                _reconnectAttempts++;
                //OnStatusChanged?.Invoke($"准备第 {_reconnectAttempts} 次重连，等待 {_currentReconnectDelay}ms...");

                Task.Delay(_currentReconnectDelay, _reconnectCts.Token).ContinueWith(t =>
                {
                    if (!t.IsCanceled && !_disposed)
                    {
                        lock (_reconnectLock)
                        {
                            if (Connect()) // 尝试重新连接
                            {
                                // 连接成功，重置退避时间
                                _currentReconnectDelay = InitialReconnectDelayMs;
                            }
                            else
                            {
                                // 计算下一次退避时间（指数增长，但不超最大值）
                                _currentReconnectDelay = (int)Math.Min(
                                    _currentReconnectDelay * BackoffMultiplier,
                                    MaxReconnectDelayMs);

                                // 安排下一次重连
                                if (_reconnectAttempts < MaxReconnectAttempts)
                                {
                                    TryReconnect();
                                }
                            }
                        }
                    }
                });
            }
        }

        #endregion （指数退避）

        #region IDisposable实现

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                _disposed = true;
                if (disposing)
                {
                    _reconnectCts?.Cancel();
                    _reconnectCts?.Dispose();
                    Disconnect();
                    _tcpClient?.Dispose();
                }
            }
        }

        ~HPSocketTcpClientService()
        {
            Dispose(false);
        }

        #endregion IDisposable实现
    }
}